#include <cstdio>
#include <cstdlib>
//#include <tchar.h>

#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/video/video.hpp"
#include <opencv2/gpu/gpu.hpp>

#include <cstring>

using namespace std;
using namespace cv;

#include "VideoRead.h"

#include "FeatureComputer.h"

#include "Classifier.h"

#include "Bagging.h"

#include "ClassifierRank.h"

#include "Interface.h"


int main(int argc, char * const argv[])
{
	//testJumpReadandTrain();

	//testJumpRead();

	bool SAVE_IN_DIFFERENT_NAME = true;


	LcInterface my_setting;

	if(argc==1)
	{
		//char *const setting_string[] ={ "","-b","-v","lb","-t","GOPR2382_cab","-s", "150", "-e", "5300", "-r","50","-p","GOPR2384_cab","-f","./../../_FGS/"};

		char *const setting_string[] ={ "","-a","-v","l","-t","GOPR2384_cab","-s", "175", "-e", "500", "-r","25","-p","GOPR2384_cab","-f","./../../_FGS/","-g","5","-j"};

		//char *const setting_string[] ={ "","-b","-v","lb","-t","GOPR2382_cab","-s", "175", "-e", "11150", "-r","25","-p","GOPR2384_cab","-f","./../../_FGS/"};

		//char *const setting_string[] ={ "","-b","-v","lb","-t","GOPR2382_cab","-s", "150", "-e", "5300", "-r","50","-p","GOPR2382_cab","-f","./../../_FGS/"};

		my_setting.input( 18 + 1 ,setting_string);
	}
	else my_setting.input( argc, argv);

	ClassifierRank my_crank;
	//Kmeans my_crank;

	LcVideoReadExt my_reader = my_setting.getTrainVideo();

	my_crank.setReader( &my_reader);

	my_crank.setFeatureCode( my_setting.feature_code_string.c_str() );

	my_crank.setClassifier( my_setting.getClassifier() );

	my_crank.IF_KMEAN = my_setting.IF_KMEAN;	

	//my_crank.trainPreFrame();

	if(my_setting.IF_TEST)
	{
		LocalSensitiveBagging crank_bagging;

		crank_bagging.setFeatureCode(my_setting.feature_code_string.c_str());

		crank_bagging.setReader( &my_reader );

		{
			string saving_name = my_reader.root + "classifier_output/crank/crank_reg_";

			if(SAVE_IN_DIFFERENT_NAME)
				saving_name = saving_name + "temp_" + my_setting.addition_str;

			crank_bagging.load( saving_name.c_str() );
		}

		LcVideoReadExt test_video = my_setting.getTestVideo();

		cout << test_video.video_name << endl;

		LcGlobalExtractor * global_extractor
			= my_setting.my_global_extractor;	

		LcValidator best_esti;
		LcValidator validator = crank_bagging.predict( test_video, *global_extractor, best_esti);

		{
			string report_name = "./report/recom_" + my_setting.train_video_name + "_on_"
				+ my_setting.test_video_name + "_v_" + my_setting.feature_code_string 
				+ my_setting.addition_str + ".txt";

			FILE * fout = fopen( report_name.c_str(),"w");

			fprintf(fout,"%f\t%f\t%f\t%f\t%f\n", validator.getF1(),
					validator.tp,validator.fp,validator.fn,validator.tn);

			fprintf(fout,"%f\t%f\t%f\t%f\t%f\n", best_esti.getF1(),
					best_esti.tp,best_esti.fp,best_esti.fn,best_esti.tn);

			fclose(fout);
		}


		//vector< LcValidator > validator_array;

		//crank_bagging.knn = 70;


		//LcValidator validator = crank_bagging.predict( test_video, *global_extractor,validator_array);

		//{
		//	string report_name = "./report/crank_report_" + my_setting.train_video_name + "_on_"
		//		+ my_setting.test_video_name + "_v_" + my_setting.feature_code_string 
		//		+ my_setting.addition_str + ".txt";

		//	FILE * fout = fopen( report_name.c_str(),"w");

		//		for(int i = 0 ; i < (int) validator_array.size() ; i++)
		//		{
		//			fprintf(fout,"%f\t%f\t%f\t%f\t%f\n", validator_array[i].getF1(),
		//				validator_array[i].tp,validator_array[i].fp,validator_array[i].fn,validator_array[i].tn);
		//			printf("%f\t%f\t%f\t%f\t%f\n", validator_array[i].getF1(),
		//				validator_array[i].tp,validator_array[i].fp,validator_array[i].fn,validator_array[i].tn);

		//		}

		//		fprintf(fout,"%f\t%f\t%f\t%f\t%f\n", validator.getF1(),
		//			validator.tp,validator.fp,validator.fn,validator.tn);

		//	fclose(fout);
		//}		

	}

	if(my_setting.IF_TRAIN)
	{

		LcGlobalExtractor * global_extractor
			= my_setting.my_global_extractor;

		my_crank.setGlobalExtractor( global_extractor);

		if(my_setting.IF_TRAIN_PER_FRAME)
		{
			my_crank.trainPreFrame();

			my_crank.crossFrameTest();
		}

		//my_crank.classifier_affine_weight = my_setting.classifier_affine_weight;

		my_crank.val = my_setting.val;
		my_crank.beta = my_setting.beta;

		my_crank.cluster_n = my_setting.cluster_n;

		

		my_crank.cluster();

		int n_classifier; int instance_limit;

		{
			FILE * fid = fopen("bagging_config.txt","r");
			fscanf(fid, "%d%d",&n_classifier, &instance_limit);
			fclose(fid);
		}

		LocalSensitiveBagging crank_bagging;

		crank_bagging.setFeatureCode(my_setting.feature_code_string.c_str());

		crank_bagging.set( my_crank, n_classifier, instance_limit);

		crank_bagging.train();


		{
			string saving_name = my_reader.root + "classifier_output/crank/crank_reg_";
			

			if(SAVE_IN_DIFFERENT_NAME)
				saving_name = saving_name + "temp_" + my_setting.addition_str;

			crank_bagging.save( saving_name.c_str() );
		}


	}

	//{
	//	my_reader.root = "./../../_FGS/";
	//	my_reader.video_name = "GOPR2384_cab";
	//	my_reader.f_start = 175;
	//	my_reader.f_end = 11150;
	//	my_reader.f_rate = 25;

	//	my_reader.veb = 1;

	//	my_crank.setReader( &my_reader);
	//}

	//LcFeatureExtractor my_extractor;

	//string feature_code = "l"; // "robvltdmchsug"

	//{
	//	my_crank.setFeatureCode( feature_code.c_str() );
	//}

	//LcRandomTrees my_classifier;

	//{
	//	my_classifier.veb = 1;
	//	my_crank.setClassifier( &my_classifier);
	//}

	//if(0){
	//	my_crank.cluster();

	//	LocalSensitiveBagging crank_bagging;

	//	crank_bagging.setFeatureCode("l");

	//	crank_bagging.set( my_crank, 1, 500000);

	//	crank_bagging.train();

	//	{
	//		string saving_name = my_reader.root + "classifier_output/crank/";
	//		crank_bagging.save( saving_name.c_str() );
	//	}
	//}
	//else
	//{
	//	LocalSensitiveBagging crank_bagging;

	//	crank_bagging.setFeatureCode("l");

	//	crank_bagging.setReader( &my_reader);

	//	{
	//		string saving_name = my_reader.root + "classifier_output/crank/";
	//		crank_bagging.load( saving_name.c_str() );
	//	}
	//}

	//system("pause");
}